#region Imported Namespace
using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections; 
using PHSRAG.Utility;
using System.Text; 
using PHSRAG.Insight21.Context;
using BO = PHSRAG.Insight21.BusinessObjects;
using InsightHumans = PHSRAG.Insight21.Humans;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;
using CDS = PHSRAG.Insight21.CDS;
using SkeltaWorkFlow = Workflow.NET;
using SkeltaEngine = Workflow.NET.Engine;
using SearchCriteria = PHSRAG.Insight21.SearchContext.SearchCriteria;
using FormsManagement = PHSRAG.Insight21.FormsManagement;
using ScriptEngine=PHSRAG.Insight21.ScriptEngine;
using Utils = PHSRAG.Insight21.InsightUtilities;
#endregion

namespace PHSRAG.Insight21.InsightWorkFlow
{
	#region Class HumansWorkFlow
	/// <summary>
	/// The methods in this class will be used by Skelta WorkFlow custom actions. This class will mainly be used as a bridge between Skelta WorkFlow
	/// and the application.
	/// </summary>
	public class HumansWorkFlow : BO.BusinessObject, IDisposable	
	{
		#region Constants
		private const string	Pi = "PI";		
		private const string	DefaultApplicationName = "EIRBWFApp";
		private const string	WorkFlowName = "EIRBWFMain";
		private const string	HumansWorkFlowKey = "HumansWorkFlowKey_134E774F-F125-46cc-B84B-E872219E86EA";	
		private const string	HROIntake = "HROIntake";
        private const string    SRACIntake = "SRACIntake";
		private const string	IRBChair = "IRBChair";
		private const int		DomainId = 1;		
		private const bool		AscendingSortSequence = true;
        private const bool      DescendingSortSequence = false;
		private const string	NWHOrganization = "NWH";
		private const string	NSMCOrganization = "NSMC";
		private const string	SRHOrganization = "SRH";
		public const string		WorkflowScriptType = "SCRIPTTYPE_WORKFLOW";
		public const string		InitialReview = "PPTYPE_IR";
        public const string     InitialWorkFlowHistory = "WFInitial";
        public const string     WorkFlowSumitter = "WFSubmitter";
        public const string     ResubmissionWFHistory = "WFResubmission";
		#endregion
       
		#region Private variables		
        private InsightHumans.ProtocolProcess   protocolProcessMember;		
		private ArrayList						staffList;		
		private	Hashtable						workflowActivityMap = new Hashtable();
        private Hashtable                       workflowErrorItemMap = new Hashtable();
        private bool                            sortAscending = AscendingSortSequence;  //DescendingSortSequence;
		private string							sortColumn = "DateAssigned";    //"ProtocolNumber";	// Keep this in sync with what the stored proc orders by
        private static string                   insightConnection = string.Empty;
        private static string                   rexConnection = string.Empty;
        private static string                   insightApplicationPath = string.Empty;
		private static string					serviceAccount = string.Empty;
		private static string					serviceAccountPwd = string.Empty;
        private static string                   insightWebService = string.Empty;
        private static string                   insightApplicationName = string.Empty;
        private static Hashtable                connections = null;
        private static Hashtable                appSettings = null;
		private static SkeltaWorkFlow.Config oworkflowConfig = null;
		#endregion

		#region Public Properties
		/// <summary>
		/// Get the key to be used in all caching operations for this instance of the object.
		/// </summary>		
		public static string CacheKey	{ get { return HumansWorkFlowKey; } }

		/// <summary>
		/// Get the key to be used in all caching operations for this instance of the object.
		/// </summary>	
		private static SkeltaWorkFlow.Config workflowConfig
		{
			get
			{
				if (oworkflowConfig == null)
				{
					oworkflowConfig = new SkeltaWorkFlow.Config(InsightApplicationName);
				}
				return oworkflowConfig;
			}
		}
		/// <summary>
		/// Get the total number of Workflow activities 
		/// </summary>
		public int ActivityCount
		{
			get
			{
				return ( null == DataContainer )? 0 :DataContainer.Tables[0].Rows.Count;
			}
		}

		/// <summary>
		/// Get the sort order.
		/// </summary>
		public bool SortAscending
		{
			get { return sortAscending; }
		}

		/// <summary>
		/// Get the name of the sort column.
		/// </summary>
		public string SortColumn
		{
			get { return sortColumn; }
		}

        #region Public static Properties
        /// <summary>
        /// Application Config(Used to setData in a thread during WorkFlow Initiation supporting the appcode to run in Skelta context)
        /// </summary>
        public static Hashtable Connections
        {
            get
            {
                if (null == connections || connections.Count == 0 )
                {
                    connections = new Hashtable();
                    connections.Add("Insight", InsightConnection);
                    connections.Add("Rex", RexConnection);
                }
                return connections;
            }
        }

        public static Hashtable AppSettings
        {
            get
            {
                if (null == appSettings)
                {
                    appSettings = new Hashtable();
                    appSettings.Add("InsightApplicationName", InsightApplicationName);
                }
                return appSettings;
            }

        }

        public static string InsightApplicationName
        {
            get
            {
                if (string.Empty == insightApplicationName)
                {
                    insightApplicationName = Utility.Settings.GetKeyValue("InsightApplicationName", DefaultApplicationName);
                }
                return insightApplicationName;
            }
            set
            {
                insightApplicationName = value;
            }
        }

        /// <summary>
        /// Insight Connection string required by the application to run in skelta context 
        /// </summary>
        public static string InsightConnection
        {
            get
            {
                if (string.Empty == insightConnection)
                {
                    SkeltaWorkFlow.Config workflowConfig;
                    workflowConfig = new SkeltaWorkFlow.Config(InsightApplicationName);
                    insightConnection = workflowConfig.DataSourceConnectionString;
                }
                return insightConnection;              
            }
        }

        /// <summary>
        /// Rex Connection string required by the application to run in skelta context 
        /// </summary>
        public static string RexConnection
        {
            get
            {
                if (string.Empty == rexConnection)
                {
                    SkeltaWorkFlow.Config workflowConfig;
                    workflowConfig = new SkeltaWorkFlow.Config(InsightApplicationName);
                    rexConnection = workflowConfig.GetAttributeDataFromXMLNode("//application[@name = '" + InsightApplicationName + "']", "rexConnection");
                }
                return rexConnection;                
            }
        }

		/// <summary>
		/// WebService service account for SOAPStation Platform
		/// </summary>
		public static string SOAPServiceAccount
		{
			get
			{
				if (string.Empty == serviceAccount)
				{
					serviceAccount = workflowConfig.GetAttributeDataFromXMLNode("//application[@name = '" + InsightApplicationName + "']", "ServiceAccount");
				}
				return serviceAccount;
			}
		}
		/// <summary>
		/// WebService service account for SOAPStation Platform
		/// </summary>
		public static string SOAPServiceAccountPwd
		{
			get
			{
				if (string.Empty == serviceAccountPwd)
				{
					serviceAccountPwd = workflowConfig.GetAttributeDataFromXMLNode("//application[@name = '" + InsightApplicationName + "']", "ServiceAccountPwd");
				}
				return serviceAccountPwd;
			}
		}
        /// <summary>
        /// Insight Web Service required by the application to run in skelta context 
        /// </summary>
        public static string InsightWebService
        {
            get
            {
                if (string.Empty == insightWebService)
                {
                    SkeltaWorkFlow.Config workflowConfig;
                    workflowConfig = new SkeltaWorkFlow.Config(InsightApplicationName);
                    insightWebService = workflowConfig.GetAttributeDataFromXMLNode("//application[@name = '" + InsightApplicationName + "']", "InsightWebService");
                }
                return insightWebService;
                
            }
        }
        /// <summary>
        /// Insight Application path required by the application to run in skelta context 
        /// </summary>
        public static string InsightApplicationPath
        {
            get
            {
                if (string.Empty == insightApplicationPath)
                {
                    SkeltaWorkFlow.Config workflowConfig;
                    workflowConfig = new SkeltaWorkFlow.Config(InsightApplicationName);
                    insightApplicationPath = workflowConfig.GetAttributeDataFromXMLNode("//application[@name = '" + InsightApplicationName + "']", "InsightApplicationPath");
                }
                return insightApplicationPath;
                
            }
        }
        #endregion
        #endregion

        #region Constructor
        /// <summary>
		/// Constructor, takes cachePolicy and sets cachepolicy of base object.
		/// </summary>
		/// <param name="cachePolicy">cachePolicy</param>
		public HumansWorkFlow(ICachePolicy cachePolicy) : base(cachePolicy)		
		{
			
		}
		
		#endregion

		#region caching
		/// <summary>
		/// Cache the current instance using the prevalent cache policy.
		/// </summary>
		public override void Cache()
		{
			CachePolicy.Cache(HumansWorkFlowKey, this);
		}

		/// <summary>
		/// Remove the current instance from the cache using the prevalent cache policy.
		/// </summary>
		public override void UnCache()
		{
			CachePolicy.UnCache(HumansWorkFlowKey);
		}
		#endregion

		#region Public Load Methods

		/// <summary>
		/// This method loads all the Protocol Processes in activity list on which users need to take actions. 				
		/// </summary>
		/// <param name="connectionString">Database connection string</param>
		/// <param name="args">Is expected to contain two arguments - Username and domain user ID</param>
		public override void Load(string connectionString, params object[] args)
		{
			Load( connectionString, null, args );
		}

		/// <summary>
		/// This method loads all the Protocol Processes activity list on which users need to take actions. 
		/// This method will call GetWorkFlowActivityList. This will also be called when Search is called on the   
		/// page. Users can give Protocol Number or Title and that will be passed to GetWorkFlowActivityList
		/// to get those particular Protocol Processes where the criteria match.
		/// </summary>
		/// <param name="connectionString">Database connection string</param>
		/// <param name="args">Is expected to contain two arguments - Username and domain user ID</param>
		/// <param name="searchCriteria">Search Criteria if there is any</param>
		public void Load(string connectionString, SearchCriteria searchCriteria, params object[] args)
		{
			try
			{
				if (args.Length != 3)
				{
					throw new Exception("Humanworkflow load requires a user name and domain user Id");
				}
				else
				{
					workflowActivityMap.Clear();
					if(searchCriteria != null) 
					{
						object protocolNumberObject = searchCriteria["protocolNumber"];
						object protocolTitleObject = searchCriteria["protocolTitle"];
						object piId = searchCriteria["PI"];
                        DataContainer = DataAccess.GetDataSet(InsightConnection,
                            "GetProtocolActivityList", Utility.DataAccess.BuildSqlParameterArray(
								"@UserName",SqlDbType.VarChar,(string)args[0],
								"@DomainUserId",SqlDbType.Int,(int)args[1],
							"@protocolNumber",SqlDbType.VarChar,(null==protocolNumberObject) ? (object)DBNull.Value : protocolNumberObject.ToString().TrimEnd('*'),
							"@protocolTitle",SqlDbType.VarChar,(null==protocolTitleObject) ? (object)DBNull.Value : protocolTitleObject.ToString().TrimEnd('*'),
							"@piId", SqlDbType.Int, (null == piId) ? (object)DBNull.Value : Convert.ToInt32(piId),
                            "@moduleType",SqlDbType.Char,(string)args[2]));
					}
					else
					{
                        DataContainer = DataAccess.GetDataSet(InsightConnection,
							"GetProtocolActivityList",Utility.DataAccess.BuildSqlParameterArray(
                            "@UserName",SqlDbType.VarChar,(string)args[0],
                            "@DomainUserId",SqlDbType.Int,(int)args[1],
                            "@moduleType",SqlDbType.Char,(string)args[2]));
					}
					if ( DataContainer.Tables.Count == 1 )
						DataContainer.Tables[0].TableName = "original";
				}
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to load Protocol Workflow Activity list", ex);
			}
		}

		#endregion
				
		#region Public Static Methods
		/// <summary>
		/// This method clears workflow item from the database.		
		/// </summary>		
		/// <param name="executionID">Workflow Execution Id</param>
		/// <returns>Activity Id</returns> 
		public static bool ClearWorkflow(int executionId)
		{
            SqlConnection connection = new SqlConnection(InsightConnection);			
			SqlTransaction transaction = null;

			bool retVal = false;	 
			try
			{
				connection.Open();
				transaction = connection.BeginTransaction("ClearWorkflow");
				DataAccess.ExecuteNonQuery(connection,transaction,"CleanWorkflowItem",Utility.DataAccess.BuildSqlParameterArray("@executionId",SqlDbType.Int,executionId));
				retVal = true;
				transaction.Commit(); 
			}
			catch (Exception ex)
			{		
				if(transaction != null)
					transaction.Rollback();
				throw new Exception("Unable to clear workflow", ex);
			}
			finally
			{
				if (connection.State != ConnectionState.Closed)
					connection.Close();
			}
			
			return retVal;
		}

        /// <summary>
        /// Gets the serialized (Xml Content)
        /// </summary>
        /// <param name="executionId">Execution Id</param>
        /// <param name="fwkDomainUserId">Framework DomainuserId</param>
        /// <param name="activityName">workflow Action name</param>
        /// <returns></returns>
        public static DataTable GetCertifiedContent(int executionId, int fwkDomainUserId, string activityName)
        {
            try
            {
                return DataAccess.GetDataTable(InsightConnection, "dbo.GetCertificationContent",
                    Utility.DataAccess.BuildSqlParameterArray
                    ("@executionId", SqlDbType.Int, executionId
                    , "@fwkDomainUserId", SqlDbType.Int, fwkDomainUserId
                    , "@activityName", SqlDbType.VarChar, activityName
                    ));
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to GET the Certified Content", ex);
            }

        }
        /// <summary>
        /// Saves the serialized xml content on Authentication(Workflow approval step)
        /// </summary>
        /// <param name="executionId">Execution Id</param>
        /// <param name="fwkDomainUserId">Framework DomainUserId</param>
        /// <param name="activityName">Activity Name (WorkFlow step name)</param>
        /// <param name="content">Serialize XMl Content</param>
        /// <param name="serverPath">Server map path</param>
        public static void SaveCertifiedContent(int executionId, int fwkDomainUserId, string activityName, string content, string serverPath)
        {
            try
            {
                DataAccess.ExecuteNonQuery(InsightConnection, "dbo.SaveCertificationContent",
                Utility.DataAccess.BuildSqlParameterArray
                                        ("@executionId", SqlDbType.Int, executionId
                                        , "@fwkDomainUserId", SqlDbType.Int, fwkDomainUserId
                                        , "@activityName", SqlDbType.VarChar, activityName
                                        , "@content", SqlDbType.NText, content
                                        , "@serverMapPath", SqlDbType.VarChar, serverPath
                                        ));
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to Save the Certified Content", ex);
            }

        }

        /// <summary>
        /// Removes the certified content from the temporary Workflow table
        /// </summary>
        /// <param name="executionId">Execution Id</param>
        /// <param name="fwkDomainUserId">Framework DomainUserId</param>
        /// <param name="activityName">Activity Name (WorkFlow step name)</param>
        public static void RemoveCertifiedContent(int executionId, int fwkDomainUserId, string activityName)
        {
            try
            {
                DataAccess.ExecuteNonQuery(InsightConnection, "dbo.DeleteCertificationContent",
                    Utility.DataAccess.BuildSqlParameterArray
                    ("@executionId", SqlDbType.Int, executionId
                    , "@fwkDomainUserId", SqlDbType.Int, fwkDomainUserId
                    , "@activityName", SqlDbType.VarChar, activityName
                    ));
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to delete the Certified Content", ex);
            }

        }


		/// <summary>
		/// Gets the history of completed activities for a process by taking in execution id as the parameter .		
		/// </summary>		
		/// <param name="executionID">Workflow Execution Id</param>
		/// <returns>Workflow history(Datetable)</returns> 
		public static DataSet GetWorkFlowHistory(int protocolProcessId, int executionId)
		{		
			DataSet wfHistory = null;
			try
			{
                wfHistory = DataAccess.GetDataSet(InsightConnection, "dbo.GetWorkFlowHistory", Utility.DataAccess.BuildSqlParameterArray("@protocolProcessId", SqlDbType.Int, protocolProcessId, "@executionId", SqlDbType.Int, executionId));
                if (wfHistory == null) return wfHistory;
                if (wfHistory.Tables.Count == 2)
                {
                    wfHistory.Tables[0].TableName = "WFHistory";
                    wfHistory.Tables[1].TableName = "WFSubmitter";
                }
                else if (wfHistory.Tables.Count == 3)
                {
                    wfHistory.Tables[0].TableName = "WFHistory";
                    wfHistory.Tables[1].TableName = "WFSubmission";
                    wfHistory.Tables[2].TableName = "WFSubmitter";
                }
                else if (wfHistory.Tables.Count == 1)
                {
                    wfHistory.Tables[0].TableName = "WFSubmitter";
                }
                else wfHistory = null;
                return wfHistory;
			}
			catch (Exception ex)
			{		
				throw new Exception("Unable to get the workflow history", ex);
			}			
		}


		/// <summary>
		/// This method returns Protocol Process Id for given Execution Id. For detail Cross reference table discussion
		/// please look GetWorkflowItemId methods summary section.		
		/// </summary>
		/// <param name="executionID">Workflow Execution Id</param> 
		/// <returns>Protocol Process ID</returns> 
		public static int GetProtocolProcessIdForWorkflowItem(int executionID)
		{
			int ppId = 0;

			//System.Diagnostics.Debugger.Break();
			
			try
			{																			
				DataSet wfPPItemMap = new DataSet();
                wfPPItemMap = DataAccess.GetDataSet(InsightConnection,
					"dbo.GetWorkflowMapData",Utility.DataAccess.BuildSqlParameterArray("@ProtocolProcessId",SqlDbType.Int,0,"@ExecutionId",SqlDbType.Int,executionID));

				if ( wfPPItemMap.Tables[0].Rows.Count >= 1 )
					ppId = Int32.Parse(wfPPItemMap.Tables[0].Rows[0]["ProtocolProcessId"].ToString()); 				
			}	
			catch (Exception ex)
			{				
				throw new Exception("Unable to get Protocol Process Id from mapping table", ex);
			}
			return ppId;

		}

        /// <summary>
        /// Checks whether the PI has approved for particular workflow
        /// </summary>
        /// <param name="executionId">Execution Id</param>        
        /// <returns></returns>
        public static bool HasPISignedOff(int executionId)
        {
            bool hasPIApproved = false;
            try
            {
                int piApproval = 0;
                piApproval = Convert.ToInt32(DataAccess.ExecuteScalar(InsightConnection,
                    "dbo.GetPIApproval", Utility.DataAccess.BuildSqlParameterArray("@ExecutionId", SqlDbType.Int, executionId)));
               
                if (piApproval > 0)
                    hasPIApproved = true;

                return hasPIApproved;
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to Get PI Approval", ex);
            }

        }
		
		#endregion

		#region Public Methods

		/// <summary>
		/// This method goeas through Quetionaire Answers and Questionaire Version objects. Depends on what forms are filled for
		/// particular Protocol Process ID and what answers are given for particular questions different Ancillary Board users are
		/// selected. These users are filled in the arraylist and sent to the Workflow. Workflow uses all these IDs to route the request
		/// accordingly.
		/// </summary>
		/// <param name="protocolId">Protocol Id</param> 
		/// <param name="protocolProcessID">Protocol Process Id</param> 
		/// <returns>UserId arraylist</returns> 
		public ArrayList GetAncillaryBoardUsers(int protocolId, int protocolProcessID)
		{
			ArrayList userList = new ArrayList();
			try
			{
                //System.Diagnostics.Debugger.Break();
				InsightHumans.ProtocolProcess protocolProcess = GetProtocolProcess(protocolProcessID);
				InsightHumans.ProtocolVersion protocolVersion = protocolProcess.GetLatestProtocolVersion(false,base.CachePolicy);
				ArrayList answersList = new ArrayList();
				bool isDrugs = false;
				bool isAnciDrugs = false;
				bool isBiologic = false;
				bool isRadiation = false;				
				bool isMGH = false;
				bool isBWH = false;
				bool isNursing = false;
				bool isBioMedical = false;
				bool isBioMedical1 = false;
				bool isBioMedical2 = false;
				bool isBioMedical3 = false;
                bool isMGHFacilitySelected = false;
                bool isBWHFacilitySelected = false;
                bool isFHFacilitySelected = false;
                bool isRadiationFormAvailable = false;
                bool isDeviceFormAvailable = false;
                bool isAncillaryDeviceFormAvailable = false;
                bool isDrugFormAvailable = false;
                bool isAncillaryDrugFormAvailable = false;               
                bool isNursingImplementationandPlanning = false;

                //Get the form type available; if user has removed the form it should remove board users from sing off
                DataSet FormTypes = FormsManagement.Questionnaire.GetFormTypes(protocolVersion.ProtocolProcessId);
                DataTable dtFormsTypes;
                if (FormTypes != null && FormTypes.Tables.Count > 0)
                {
                    dtFormsTypes = FormTypes.Tables[0];
                    foreach (DataRow dr in dtFormsTypes.Rows)
                    {
                        if (dr[1].ToString() == Utility.Settings.GetKeyValue("NonIonizingRadiation", "Non-Ionizing Radiation") || dr[1].ToString() == Utility.Settings.GetKeyValue("IonizingRadiation", "Ionizing Radiation"))
                            isRadiationFormAvailable = true;

                        if (dr[1].ToString() == Utility.Settings.GetKeyValue("AncillaryDrugs", "Ancillary Drugs"))
                            isAncillaryDrugFormAvailable = true;

                        if (dr[1].ToString() == Utility.Settings.GetKeyValue("AncillaryDevices", "Ancillary Devices"))
                            isAncillaryDeviceFormAvailable = true;

                        if (dr[1].ToString() == Utility.Settings.GetKeyValue("Drugs", "Drugs / Biologics / Dietary Supplements"))
                            isDrugFormAvailable = true;

                        if (dr[1].ToString() == Utility.Settings.GetKeyValue("MedicalDevices", "Medical Devices"))
                            isDeviceFormAvailable = true;

                        if (dr[1].ToString() == Utility.Settings.GetKeyValue("NursingImplementationandPlanning", "Nursing Implementation and Planning"))
                            isNursingImplementationandPlanning = true;
                    }
                }

                answersList = protocolVersion.QuestionnaireAnswers;

                for (int count = 0; count <= answersList.Count - 1; ++count)
                {
                    FormsManagement.QuestionnaireAnswer questionaireAnswer = (FormsManagement.QuestionnaireAnswer)answersList[count];
                    FormsManagement.QuestionnaireVersion questionaireVer = questionaireAnswer.QuestionnaireVersion;
                    FormsManagement.Questionnaire questionaire = new FormsManagement.Questionnaire(base.CachePolicy);
                   
					questionaire.Load(InsightConnection,questionaireVer.QuestionnaireID);
					if ((questionaire.Name == "InitialReview") && (questionaire.Type == FormsManagement.Constants.QuestionnaireType.InitialApplication))
					{
						//string answer1 = (questionaireAnswer.GetAnswers("Drug").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("Drug")[0]).Value;
                        if (isDrugFormAvailable)											
							isDrugs = true;
						
						//answer1 = (questionaireAnswer.GetAnswers("Ionizing").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("Ionizing")[0]).Value;
						//string answer2 = (questionaireAnswer.GetAnswers("NonIonizing").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("NonIonizing")[0]).Value;

                        if (isRadiationFormAvailable)						
							isRadiation = true;						

						//answer1 = (questionaireAnswer.GetAnswers("Device").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("Device")[0]).Value;
						if (isDeviceFormAvailable)				   
							isBioMedical1 = true;
						
						//answer1 = (questionaireAnswer.GetAnswers("Patients").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("Patients")[0]).Value;
						if (isNursingImplementationandPlanning)
							isNursing = true;
					}
				}
				for (int count = 0; count <= answersList.Count - 1; ++count)
				{					
					FormsManagement.QuestionnaireAnswer questionaireAnswer = (FormsManagement.QuestionnaireAnswer)answersList[count];
					FormsManagement.QuestionnaireVersion questionaireVer = questionaireAnswer.QuestionnaireVersion; 
					FormsManagement.Questionnaire questionaire = new FormsManagement.Questionnaire(base.CachePolicy);
					questionaire.Load(InsightConnection,questionaireVer.QuestionnaireID);
					if (isDrugs && (questionaire.Category == FormsManagement.Constants.CommonFormCategory.Drugs)) 						
					{								
						string answer = (questionaireAnswer.GetAnswers("TypeAgent2").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("TypeAgent2")[0]).Value;						
						if ((answer == "TypeBiologic") && isDrugFormAvailable)						
							isBiologic = true;					
					}
                    
					if (questionaire.Category == FormsManagement.Constants.CommonFormCategory.Devices)				   
					{
                        string answer = "N";
						answer = (questionaireAnswer.GetAnswers("ElectricDevice").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("ElectricDevice")[0]).Value;
                        if ((answer == "Y") && isDeviceFormAvailable)
                        {
                            isBioMedical2 = true;

                            answer = (questionaireAnswer.GetAnswers("MGHFacility").Count == 0) ? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("MGHFacility")[0]).Value;
                            if (answer == "MGH")
                            {
                                isMGHFacilitySelected = true;                                
                            }
                            answer = (questionaireAnswer.GetAnswers("BWHFacility").Count == 0) ? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("BWHFacility")[0]).Value;
                            if (answer == "BWH")
                            {
                                isBWHFacilitySelected = true;                                
                            }
                            answer = (questionaireAnswer.GetAnswers("FHFacility").Count == 0) ? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("FHFacility")[0]).Value;
                            if (answer == "FH")
                            {
                                isFHFacilitySelected = true;
                            }
                        }
					}
					if ((questionaire.Name == "AncillaryDevices") || (questionaire.Name == "Ancillary Devices"))
					{
						string answer1 = (questionaireAnswer.GetAnswers("AncillaryDevices").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("AncillaryDevices")[0]).Value;
						string answer2 = (questionaireAnswer.GetAnswers("DeviceElectricPower").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("DeviceElectricPower")[0]).Value;
						if (answer2 == "Y" && isAncillaryDeviceFormAvailable)	
							isBioMedical3 = true;

					}
					if ((questionaire.Name == "AncillaryDrugs") || (questionaire.Name == "Ancillary Drugs"))
					{
						string answer1 = (questionaireAnswer.GetAnswers("AncillaryDrugs").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("AncillaryDrugs")[0]).Value;
                        if (answer1 == "Y" && isAncillaryDrugFormAvailable)
							isAnciDrugs = true;
					}					

					if (questionaire.Name == "Performance Sites") //Check whether BWH or MGH are checked
					{
						//Drugs Questionaire. Now check which Organization is checked.
						string siteBWH = (questionaireAnswer.GetAnswers("SiteBWH").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("SiteBWH")[0]).Value;
						string siteMGH = (questionaireAnswer.GetAnswers("SiteMGH").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("SiteMGH")[0]).Value;

						if (siteBWH == "BWH") //Whether BWH is checked in the forms
							isBWH = true;
						if (siteMGH == "MGH") //Whether MGH is checked in the forms
							isMGH = true;
					}					
				}

				if (isBioMedical1 || isBioMedical3)
				{
					isBioMedical = true;
				}

				//Now we have all the data of the questions get the particular Ancillary Board users.
				if (isDrugs || isAnciDrugs)
				{
					if (isBWH)								
						userList.Add(GetWorkflowPerson(2,"BWHInvestigationalDrugServiceContact"));						
					if (isMGH)					
						userList.Add(GetWorkflowPerson(3,"MGHInvestigationalDrugServiceContact"));						
				}

                if (isBiologic)
                {
                    if (isBWH)
                        userList.Add(GetWorkflowPerson(2, "BWHBioSafetyContact"));
                    if (isMGH)
                        userList.Add(GetWorkflowPerson(3, "MGHBioSafetyContact"));
                }

                if (isBioMedical2)
                {
                    int userId = 0;
                    if (isBWHFacilitySelected)
                    {
                        userId = GetWorkflowPerson(2, "BWHElectricDeviceSafetyContact");
                        if (!userList.Contains(userId) && userId != 0)
                            userList.Add(userId);
                    }
                    if (isMGHFacilitySelected)
                    {
                        userId = 0;
                        userId = GetWorkflowPerson(3, "MGHElectricDeviceSafetyContact");
                        if (!userList.Contains(userId) && userId != 0)
                            userList.Add(userId);
                    }
                    if (isFHFacilitySelected)
                    {
                        userId = 0;
                        userId = GetWorkflowPerson(604, "FHElectricDeviceSafetyContact");
                        if (!userList.Contains(userId) && userId != 0)
                            userList.Add(userId);
                    }
                }					

				if (isRadiation)
				{
					if (isBWH)											
						userList.Add(GetWorkflowPerson(2,"BWHRadiationSafetyContact"));						
					if (isMGH)											
						userList.Add(GetWorkflowPerson(3,"MGHRadiationSafetyContact"));					
				}

				if (isBioMedical)
				{
					if (isBWH)
						userList.Add(GetWorkflowPerson(2,"BWHBiomedicalEngineeringContact"));						
					if (isMGH)
						userList.Add(GetWorkflowPerson(3,"MGHBiomedicalEngineeringContact"));						
				}

				if (isNursing)
				{
					if (isBWH)										
						userList.Add(GetWorkflowPerson(2,"BWHNursingContact"));						
					if (isMGH)					
						userList.Add(GetWorkflowPerson(3,"MGHNursingContact"));					
				}
				
				return userList;
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to get Ancillary Board Users", ex);
			}		
		}		
		
		/// <summary>
		/// This method goeas through Quetionaire Answers and Questionaire Version objects. Depends on forms that are selected for amendment
		/// selected.
		/// </summary>
		/// <param name="protocolId">Protocol Id</param> 
		/// <param name="protocolProcessID">Protocol Process Id</param> 
		/// <returns>UserId arraylist</returns> 
		public ArrayList GetAncillaryBoardUsersForNonIR(int protocolId, int protocolProcessID)
		{			
			ArrayList userList = new ArrayList();
			
			try
			{
				InsightHumans.ProtocolProcess protocolProcess = GetProtocolProcess(protocolProcessID);
				InsightHumans.ProtocolVersion protocolVersion = protocolProcess.GetLatestProtocolVersion(false,base.CachePolicy);
				ArrayList answersList = new ArrayList();
				bool isDrugs = false;
				bool isAnciDrugs = false;
				bool isDevices=false;
				bool isAncillaryDevices = false;
				bool isRadiation = false;
				bool isNursing = false;
				bool isMGH = false;
				bool isBWH = false;
				bool isBioSafety = false;
				bool isBioEngineering = false;
				bool isPerfomanceSiteAvailable=false;
                bool isMGHFacilitySelected = false;
                bool isBWHFacilitySelected = false;
                bool isFHFacilitySelected = false;                               
                bool isRadiationFormAvailable = false;
                bool isDeviceFormAvailable = false;
                bool isAncillaryDeviceFormAvailable = false;
                bool isDrugFormAvailable = false;
                bool isAncillaryDrugFormAvailable = false;
                bool isNursingImplementationandPlanning = false;

                DataSet FormTypes = FormsManagement.Questionnaire.GetFormTypes(protocolVersion.ProtocolProcessId);
                DataTable dtFormsTypes;

                //Get the form type available; if user has removed the form it should remove board users from sing off
                if (FormTypes.Tables.Count > 0)
                {
                    dtFormsTypes = FormTypes.Tables[0];
                    foreach (DataRow dr in dtFormsTypes.Rows)
                    {
                        if (dr[1].ToString() == Utility.Settings.GetKeyValue("NonIonizingRadiation", "") || dr[1].ToString() == Utility.Settings.GetKeyValue("IonizingRadiation", ""))
                            isRadiationFormAvailable = true;

                        if (dr[1].ToString() == Utility.Settings.GetKeyValue("AncillaryDrugs", ""))
                            isAncillaryDrugFormAvailable = true;

                        if (dr[1].ToString() == Utility.Settings.GetKeyValue("AncillaryDevices", ""))
                            isAncillaryDeviceFormAvailable = true;

                        if (dr[1].ToString() == Utility.Settings.GetKeyValue("Drugs", ""))
                            isDrugFormAvailable = true;

                        if (dr[1].ToString() == Utility.Settings.GetKeyValue("MedicalDevices", ""))
                            isDeviceFormAvailable = true;

                        if (dr[1].ToString() == Utility.Settings.GetKeyValue("NursingImplementationandPlanning", ""))
                            isNursingImplementationandPlanning = true;
                    }
                }
								
				answersList = protocolVersion.QuestionnaireAnswers;								
				
				for (int count = 0; count <= answersList.Count - 1; ++count)
				{					
					FormsManagement.QuestionnaireAnswer questionaireAnswer = (FormsManagement.QuestionnaireAnswer)answersList[count];
					FormsManagement.QuestionnaireVersion questionaireVer = questionaireAnswer.QuestionnaireVersion; 					
                    FormsManagement.Questionnaire questionaire = new FormsManagement.Questionnaire(base.CachePolicy);

                    questionaire.Load(InsightConnection,questionaireVer.QuestionnaireID);

					if ((questionaire.Name == "Amendment") && (questionaire.Type == FormsManagement.Constants.QuestionnaireType.Amendment))
					{
						/****Step:1 Check For Drugs and Ancillary Drugs*******/
						//If isDrugs/isAnciDrugs then get the userlist for the selected site's Ancillary board(Investigational drug service/Research pharmacy commitee)
						string answer1 = (questionaireAnswer.GetAnswers("AncillaryDrug").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("AncillaryDrug")[0]).Value;						

						if ((answer1 == "AncillaryDrug") && isAncillaryDrugFormAvailable)
						{						
							isAnciDrugs = true;
						}

						answer1 = (questionaireAnswer.GetAnswers("Drugs").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("Drugs")[0]).Value;						
						if ((answer1 == "Drugs") && isDrugFormAvailable)
						{						
							isDrugs = true;
						}
						/****End of Step:1*******/

						/****Step:2 Check For Devices and Ancillary Device*******/
						//If isDevices/isAncillaryDevices then get the userlist for the selected site's Ancillary board(Investigational drug service/Research pharmacy commitee) 
						answer1 = (questionaireAnswer.GetAnswers("AncillaryDevice").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("AncillaryDevice")[0]).Value;						
						if ((answer1 == "AncillaryDevice") && isAncillaryDeviceFormAvailable)
						{						
							isAncillaryDevices = true;
						}

						answer1 = (questionaireAnswer.GetAnswers("Device").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("Device")[0]).Value;
						if ((answer1 == "Device") && isDeviceFormAvailable)				   
						{
							isDevices = true;
						}
						/****End of Step:2*******/

						/****Step:3 Check For Ionizing/Non-Ionizing *******/
						//If isRadiation then get the userlist for the selected site's Ancillary board(Radiation Safety Commitee) 
						answer1 = (questionaireAnswer.GetAnswers("IonizingRad").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("IonizingRad")[0]).Value;
						string answer2 = (questionaireAnswer.GetAnswers("NonIonizingRad").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("NonIonizingRad")[0]).Value;
                        if ((answer1 == "IonizingRad" || answer2 == "NonIonizingRad") && isRadiationFormAvailable)
						{
							isRadiation = true;
						}
						/****End of Step:3*******/
						
						/****Step:4 Check for Nursing*******/
						//If isNursing then get the userlist for the selected site's Ancillary board(Nursing) 
						//answer1 = (questionaireAnswer.GetAnswers("Nursing").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("Nursing")[0]).Value;
						if (isNursingImplementationandPlanning)				   
						{
							isNursing = true;
						}
						/****End of Step:4*******/
					}
				}
				for (int count = 0; count <= answersList.Count - 1; ++count)
				{					
					FormsManagement.QuestionnaireAnswer questionaireAnswer = (FormsManagement.QuestionnaireAnswer)answersList[count];
					FormsManagement.QuestionnaireVersion questionaireVer = questionaireAnswer.QuestionnaireVersion; 
					FormsManagement.Questionnaire questionaire = new FormsManagement.Questionnaire(base.CachePolicy);
					questionaire.Load(InsightConnection,questionaireVer.QuestionnaireID);

					if (isDrugs && (questionaire.Category == FormsManagement.Constants.CommonFormCategory.Drugs)) 						
					{								
						string answer = (questionaireAnswer.GetAnswers("TypeAgent2").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("TypeAgent2")[0]).Value;						
						if ((answer == "TypeBiologic" || answer == "TypeDrugBiologic")  && isDrugFormAvailable)						
							isBioSafety = true;	//Should get the list of users from the bio-safety dept.		
					}
					if (isDevices &&(questionaire.Category == FormsManagement.Constants.CommonFormCategory.Devices))
                    {
                        string answer = "N";
						answer = (questionaireAnswer.GetAnswers("ElectricDevice").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("ElectricDevice")[0]).Value;
						if ((answer == "Y") && isDeviceFormAvailable)	
                        {
							isBioEngineering = true;//Should get the list of users from PHS BioMedicalEngineering dept.
                            answer = (questionaireAnswer.GetAnswers("MGHFacility").Count == 0) ? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("MGHFacility")[0]).Value;
                            if (answer == "MGH")
                            {
                                isMGHFacilitySelected = true;                                   
                            }
                            answer = (questionaireAnswer.GetAnswers("BWHFacility").Count == 0) ? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("BWHFacility")[0]).Value;
                            if (answer == "BWH")
                            {
                                isBWHFacilitySelected = true;                                    
                            }
                            answer = (questionaireAnswer.GetAnswers("FHFacility").Count == 0) ? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("FHFacility")[0]).Value;
                            if (answer == "FH")
                            {
                                isFHFacilitySelected = true;
                            }                            
                        }
					}
					if (questionaire.Name == "Ancillary Devices")
					{
						string answer = (questionaireAnswer.GetAnswers("DeviceElectricPower").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("DeviceElectricPower")[0]).Value;
						if (answer == "Y" && isAncillaryDevices)	
							isBioEngineering = true;//Should get the list of users from PHS BioMedicalEngineering dept.
					}
					
					if ((questionaire.Name == "PerformanceSites")||(questionaire.Name == "Performance Sites")) //Check whether BWH or MGH are checked
					{
						isPerfomanceSiteAvailable=true;
						//Drugs Questionaire. Now check which Organization is checked.
						string siteBWH = (questionaireAnswer.GetAnswers("SiteBWH").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("SiteBWH")[0]).Value;
						string siteMGH = (questionaireAnswer.GetAnswers("SiteMGH").Count == 0)? string.Empty : ((FormsManagement.Answer)questionaireAnswer.GetAnswers("SiteMGH")[0]).Value;

						if (siteBWH == "BWH") //Whether BWH is checked in the forms
						{
							isBWH = true;
						}
						if (siteMGH == "MGH") //Whether MGH is checked in the forms
						{
							isMGH = true;
						}
					}					
				}
				if (!isPerfomanceSiteAvailable)
				{
					//CheckFor the Last available performance sites.(!.e. from Initial review)
					GetPerformanceSites(protocolId,out isBWH,out isMGH);
				}
				//Now we have all the data of the questions get the particular Ancillary Board users.
				if(isDrugs || isAnciDrugs)
				{
					if (isBWH)
					{			
						userList.Add(GetWorkflowPerson(2,"BWHInvestigationalDrugServiceContact"));						
					}
					if (isMGH)
					{			
						userList.Add(GetWorkflowPerson(3,"MGHInvestigationalDrugServiceContact"));						
					}
				}
				if (isDrugs && isBioSafety)
				{					
					if (isBWH)
					{	
						userList.Add(GetWorkflowPerson(2,"BWHBioSafetyContact"));						
					}
					if (isMGH)
					{						
						userList.Add(GetWorkflowPerson(3,"MGHBioSafetyContact"));						
					}
				}
				if (isRadiation)
				{					
					if (isBWH)
					{		
						userList.Add(GetWorkflowPerson(2,"BWHRadiationSafetyContact"));						
					}
					if (isMGH)
					{		
						userList.Add(GetWorkflowPerson(3,"MGHRadiationSafetyContact"));						
					}
				}
				if (isNursing)
				{
					if (isBWH)
					{						
						userList.Add(GetWorkflowPerson(2,"BWHNursingContact"));						
					}
					if (isMGH)
					{	
						userList.Add(GetWorkflowPerson(3,"MGHNursingContact"));						
					}
				}
				if (isBioEngineering)
				{
                    int userId = 0;
                    if (isBWHFacilitySelected)
                    {   userId = GetWorkflowPerson(2, "BWHElectricDeviceSafetyContact");
                        if (!userList.Contains(userId) && userId !=0)
                            userList.Add(userId);                      
                    }
                    if (isMGHFacilitySelected)
                    {
                        userId = 0;
                        userId = GetWorkflowPerson(3, "MGHElectricDeviceSafetyContact");
                        if (!userList.Contains(userId) && userId != 0)
                            userList.Add(userId);  
                    }
                    if (isFHFacilitySelected)
                    {
                        userId = 0;
                        userId = GetWorkflowPerson(604, "FHElectricDeviceSafetyContact");
                        if (!userList.Contains(userId) && userId != 0)
                            userList.Add(userId); 
                    }                        
				}				
				
				return userList;
			}
			catch (Exception ex)
			{
				Utility.ExceptionReport.WriteToEventLog ("Unable to get Ancillary Board Users", ex, true, Utility.ExceptionReport.ReportType.Error);
				throw new Exception("Unable to get Ancillary Board Users", ex);
			}		
		}
        /// <summary>
        /// This method goeas through Quetionaire Answers and Questionaire Version objects. Depends on what forms are filled for
        /// particular Protocol Process ID and what answers are given for particular questions different Ancillary Board users are
        /// selected. These users are filled in the arraylist and sent to the Workflow. Workflow uses all these IDs to route the request
        /// accordingly.
        /// </summary>
        /// <param name="protocolId">Protocol Id</param> 
        /// <param name="protocolProcessID">Protocol Process Id</param> 
        /// We have only one institution(MGH) using this at present and hence only MGH ancillary board users will be used
        /// <returns>UserId arraylist</returns> 
        public ArrayList GetAnimalsAncillaryBoardUsers(int protocolId, int protocolProcessID)
        {
            ArrayList userList = new ArrayList();
           
            try
            {
                const string BIO = "bio";
                const string CHEM = "chem";
                const string RAD = "rad";
                bool isBio = false;
                bool isRad = false;
                bool isChem = false;
                InsightHumans.ProtocolProcess protocolProcess = GetProtocolProcess(protocolProcessID);
                InsightHumans.ProtocolVersion protocolVersion = protocolProcess.GetLatestProtocolVersion(false, base.CachePolicy);
                ArrayList answersList = new ArrayList();

                answersList = protocolVersion.QuestionnaireAnswers;
                for (int count = 0; count <= answersList.Count - 1; ++count)
                {
                    FormsManagement.QuestionnaireAnswer questionaireAnswer = (FormsManagement.QuestionnaireAnswer)answersList[count];
                    FormsManagement.QuestionnaireVersion questionaireVer = questionaireAnswer.QuestionnaireVersion;

                    FormsManagement.Questionnaire questionaire = new FormsManagement.Questionnaire(base.CachePolicy);
                    questionaire.Load(InsightConnection, questionaireVer.QuestionnaireID);
                    if (questionaire.Category == FormsManagement.Constants.AnimalsFormCatgory.Hazardous) 
                    {
                        if (questionaireAnswer.GetAnswers("HazardType").Count != 0)
                        {
                            switch (((FormsManagement.Answer)questionaireAnswer.GetAnswers("HazardType")[0]).Value.ToLower())
                            {
                                case BIO:
                                    isBio = true;                                    
                                    break;
                                case CHEM:
                                    isChem = true;                                    
                                    break;
                                case RAD:
                                    isRad = true;                                   
                                    break;
                               default:
                                   break;
                            }                              
                            
                        }
                    }
                }
                if (isBio)
                    userList = GetWorkflowPeople(2, "MGHAnimalsBioSafety", protocolProcessID);
                if (isChem)
                    userList = GetWorkflowPeople(2, "MGHAnimalsSafety", protocolProcessID);
                if (isRad)
                    userList= GetWorkflowPeople(2, "MGHAnimalsRadiationSafety", protocolProcessID);
                
                return userList;
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to get Ancillary Board Users", ex);
            }
        }		
		/// <summary>
		/// This method gets contact people for the Protocol.
		/// </summary>		
		/// <param name="protocolProcessID">Protocol Process Id</param> 
		/// <returns>Contact people arraylist</returns> 
		public ArrayList GetContactPeople(int protocolProcessID)
		{
			ArrayList userList = new ArrayList();
			try
			{
				InsightHumans.ProtocolProcess protocolProcess = GetProtocolProcess(protocolProcessID);
				ArrayList studyStaffList = GetStudyStaff(protocolProcess); 
				int staffCount = studyStaffList.Count; 

				InsightHumans.StaffPerson  staffPerson = null;
				for(int count = 0; count < staffCount; ++count)
				{
					staffPerson = (InsightHumans.StaffPerson) studyStaffList[count];										
					if (staffPerson.IsContactPerson)
					{
						userList.Add(staffPerson.UserId);
					}
				}
				return userList;

			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to get Contact people", ex);			
			}

		}

		/// <summary>
		/// This method returns the user Role for the current protocol process ID.
		/// This role is used in DocumentView window to display proper fields.
		/// These fields are Role and process specific. The proess will be taken from 
		/// input parameter of Execute method of WorkFlow.
		/// </summary>
		/// <param name="protocolProcessId">Protocol Process Id</param> 
		/// <returns>User role</returns> 
		public string GetCurrentRole(int protocolProcessId)
		{			
			string userRole = string.Empty;
			try
			{
				UserContext userContext = (UserContext)base.CachePolicy.GetCachedObject(UserContext.CacheKey);
				InsightHumans.ProtocolProcess protocolProcess = GetProtocolProcess(protocolProcessId);
				int userID = userContext.DomainUserId;									 														
				InsightHumans.StaffPerson  staffPerson;
				ArrayList studyStaffList = GetStudyStaff(protocolProcess);
				int staffCount = studyStaffList.Count; 
				for(int count = 0; count < staffCount; ++count)
				{
					staffPerson = (InsightHumans.StaffPerson)studyStaffList[count];
					if (staffPerson.AdmPersonId == userID)
					{
						userRole = staffPerson.Role; 
						break;
					}
				}
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to get current role", ex);
			}
			return userRole;
		}		

		/// <summary>
		/// This method returns workflow submitter activity Id for passed workflow execution id.
		/// This is used by Approval process using Skelta API.
		/// </summary>		
		/// <param name="executionID">Workflow Execution Id</param>
		/// <returns>Activity Id</returns> 
		public int GetLatestSubmitterActivityId(int executionId)
		{			
			int activityId = 0;			
			try
			{		
				DataSet wfActivity = new DataSet();
                wfActivity = DataAccess.GetDataSet(InsightConnection,
					"GetLatestWorkflowActivity",Utility.DataAccess.BuildSqlParameterArray("@ExecutionId",SqlDbType.Int,executionId));
				if (wfActivity.Tables.Count > 0)
				{
					if (wfActivity.Tables[0].Rows.Count > 0)
					{
						//Append first characters is just to make sure that if the name starts with Submitter then it will not be invalid case.
                        string activityName = "^" + wfActivity.Tables[0].Rows[0]["ActivityName"].ToString(); 						
						if (activityName.IndexOf("Submitter",0) > 0)
						{
							activityId = Int32.Parse(wfActivity.Tables[0].Rows[0]["ActivityId"].ToString());					
						}
					}
				}

			}	
			catch (Exception ex)
			{				
				throw new Exception("Unable to get Activity Id", ex);

			}
			return activityId;
		}
			
		/// <summary>
		/// This method is getting a type of Process from Workflow context variable. When workflow gets submitted, type of the
		/// process gets passed to the workflow engine in XML format (Please refere to InitiateWorkFlow for more details).
		/// This method gets that type and sends it to callee.  
		/// </summary>	
		/// <param name="protocolProcessId">Protocol Process Id</param> 
		/// <returns>Type of Protocol Process</returns> 
		public string GetProtocolProcessType(int protocolProcessId)
		{				
			try
			{
				return GetContextVariables("Content", "pptype",protocolProcessId);
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to get Protocol Process Type", ex);
			}			
		}		

		public string GetProtocolProcessType(int protocolProcessId, string WFType)
		{				
			try
			{
				return GetContextVariables("Content", "pptype",protocolProcessId, WFType);
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to get Protocol Process Type", ex);
			}			
		}		


		/// <summary>
		/// This method gets Protocol object.
		/// </summary>
		/// <param name="protocolsID">Protocol Id</param> 
		/// <returns>InsightHumans.Protocol object</returns>
		public InsightHumans.Protocol GetProtocol(int protocolId)
		{
			InsightHumans.Protocol protocol=null;
			if (protocolId!=0)
			{
				protocol=new PHSRAG.Insight21.Humans.Protocol(base.CachePolicy);
				protocol.Load(InsightConnection,protocolId);
			}
			return protocol;
		}
		
		/// <summary>
		/// This method gets Protocol Administrator for the Protocol.
		/// </summary>		
		/// <param name="protocolProcessID">Protocol Process Id</param> 
		/// <returns>Protocol Administrator ID</returns> 
		public int GetProtocolAdministrator(int protocolProcessID)
		{			
			try
			{   
				InsightHumans.ProtocolProcess protocolProcess = GetProtocolProcess(protocolProcessID);
				InsightHumans.Protocol protocol = new PHSRAG.Insight21.Humans.Protocol(base.CachePolicy);
				protocol.Load(InsightConnection,protocolProcess.ProtocolId);				
				return protocol.AdministratorDomainUserId; 				
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to get Protocol Administrator", ex);			
			}
		}

		/// <summary>
		/// This method gets Protocol Process object.
		/// </summary>
		/// <param name="protocolProcessID">Protocol Process Id</param> 
		/// <returns>InsightHumans.ProtocolProcess object</returns>
		public InsightHumans.ProtocolProcess GetProtocolProcess(int protocolProcessID)
		{
            if (protocolProcessMember == null)
			{
                protocolProcessMember = InsightHumans.ProtocolProcess.GetProtocolProcess(
                    InsightConnection, protocolProcessID, base.CachePolicy, null);
			}
            return protocolProcessMember;
		}


		/// <summary>
		/// <summary>
		/// This method retuns the arraylist of answers for the required questionnaire name .The protocolProcessId is required as input along with the questionnaire name and questionnaireItemName. 
		/// </summary>
		/// <param name="protocolProcess">The process Id to which the questionnaire is asssosiated with</param>
		/// <param name="questionnaireCategory">The Questionnaire name of the questionnaire.</param>
		/// <param name="questionnaireItemName">The Questionnaire Item Name.</param>
		/// <returns>ArrayList</returns>
		public ArrayList GetQIAnsByQName(int protocolProcessId,string questionnaireName,string questionnaireItemName)
		{	
			try
			{
				Humans.ProtocolProcess protocolProcess=GetProtocolProcess(protocolProcessId);
				if(null ==protocolProcess)
				{return null;}
				return GetQIAnsByQName(protocolProcess,questionnaireName,questionnaireItemName);
			}
			catch(Exception ex)
			{throw new Exception("Failed to get the QIanswers. Error occurred at HumansWorkFlow.GetQIAnsByQName() " + ex.InnerException.ToString());}
		}

		/// <summary>
		/// This method retuns the arraylist of answers for the required questionnaire name .The protocolProcess is required as input along with questionnaire category or the questionnaire name. 
		/// Note:Atleast category or name is required for the questionnaire.
		/// </summary>
		/// <param name="protocolProcess">The process to which the questionnaire is asssosiated</param>
		/// <param name="questionnaireName">The Questionnaire category of the questionnaire.</param>
		/// <param name="questionnaireItemName">The Questionnaire Item Name.</param>
		/// <returns></returns>
		public ArrayList GetQIAnsByQName(InsightHumans.ProtocolProcess protocolProcess,string questionnaireName,string questionnaireItemName)
		{	
			ArrayList answerList=null;
			try
			{
				answerList=GetQuestionnaireAnswers(protocolProcess);
				for (int count = 0; count < answerList.Count ; ++count)
				{					
					FormsManagement.QuestionnaireAnswer questionaireAnswer = (FormsManagement.QuestionnaireAnswer)answerList[count];
					FormsManagement.QuestionnaireVersion questionaireVer = questionaireAnswer.QuestionnaireVersion; 
					FormsManagement.Questionnaire questionaire = new FormsManagement.Questionnaire(base.CachePolicy);
					questionaire.Load(InsightConnection,questionaireVer.QuestionnaireID);
					if (questionaire.Name == questionnaireName)
					{		
						answerList= questionaireAnswer.GetAnswers(questionnaireItemName);
					}
				}
				return answerList;
			}
			catch(Exception ex)
			{throw new Exception("Failed to get the QIanswers. Error occurred at HumansWorkFlow.GetQIAnsByQName() " + ex.InnerException.ToString());}
		}

		/// <summary>
		/// This method is returns the value of Resubmission flag for particular Protocol Process		
		/// </summary>	
		/// <param name="protocolProcessId">Protocol Process Id</param> 
		/// <returns>Resubmission flag value</returns> 
		public int GetResubmissionFlag(int protocolProcessId)
		{
			try
			{
				return Int32.Parse(GetContextVariables("Variable", "resubmissionflag",protocolProcessId));
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to get workflow resubmission flag", ex);
			}			

		}

		public int GetResubmissionFlag(int protocolProcessId, string WFType)
		{
			try
			{
				return Int32.Parse(GetContextVariables("Variable", "resubmissionflag",protocolProcessId, WFType));
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to get workflow resubmission flag", ex);
			}			

		}

		/// <summary>
		/// This method gets Study staff list associated with a Protocol Process
		/// </summary>
		/// <param name="pProcess">Protocol Process Object</param>
		/// <returns>Study staff array list</returns>
		public ArrayList GetStudyStaff(InsightHumans.ProtocolProcess pProcess)
		{
			if (staffList == null)
			{
				staffList = pProcess.StudyStaff;				 				
			}
			
			return staffList;
		}

		/// <summary>
		/// This method will get all other study staffs other than PI, Site PI (i.e. Critical Study Staff) if the process type is InitialReview.
		/// Otherwise, it will get all study staff. It goes to Study staff collection and gets study staff for given Protocol Process. 		
		/// </summary>		
		/// <param name="protocolProcessID">Protocol Process Id</param> 		
		public ArrayList GetStudyStaffUsers(int protocolProcessID,out ArrayList criticalStudyStaffList,out int addedPiUserId)
		{                 
			ArrayList studyStaffUserList = new ArrayList();
			criticalStudyStaffList = new ArrayList();
			addedPiUserId=0;

			try
			{     
                //System.Diagnostics.Debugger.Break();
				ArrayList studyStaffList = GetStudyStaff(GetProtocolProcess(protocolProcessID)); 
				InsightHumans.ProtocolProcess protocolProcess = GetProtocolProcess(protocolProcessID);
				string processType = protocolProcess.Type;
				int staffCount = studyStaffList.Count; 

				for(int count = 0; count < staffCount; ++count)
				{
					InsightHumans.StaffPerson  staffPerson = (InsightHumans.StaffPerson) studyStaffList[count];

					if (staffPerson.AddedProtocolProcessId == protocolProcessID)
					{                             
						if (staffPerson.RoleId == InsightHumans.Constants.StaffRoleType.PrincipalInvestigator) 
						{
							addedPiUserId=staffPerson.UserId;
						}

						else if(staffPerson.RoleId == InsightHumans.Constants.StaffRoleType.SiteResponsibleInvestigator)

						{
							criticalStudyStaffList.Add(staffPerson.UserId);
						}
						else
						{
							studyStaffUserList.Add(staffPerson.UserId);                                         
						}
					}
				}
			}
			catch (Exception ex)
			{                       
				throw new Exception("Unable to get study staff users", ex);
			}
			return studyStaffUserList;
		}

		/// <summary>
		/// This method is used load WorkflowActivityMap hashtable which gets bind on WorkflowActivity page on the datagrid.
		/// </summary>
		/// <param name="startIndex">Start Index</param>
		/// <param name="count">Number of records</param>
		/// <returns>Datatable used by grid on Workflow activity page</returns>
		public DataTable GetWorkflowActivityList(int startIndex, int count)
		{
			DataTable workflowActivityList;
			try
			{
				workflowActivityList = workflowActivityMap[startIndex] as DataTable;
				if (workflowActivityList == null)
				{
					workflowActivityList = new DataTable();					
					DataTable dataTable = DataContainer.Tables["original"]; 
					workflowActivityList = dataTable.Clone();					
					for (int iCount = startIndex, end = Math.Min(iCount + count, dataTable.Rows.Count); iCount < end; ++iCount)
					{
						workflowActivityList.LoadDataRow(dataTable.Rows[iCount].ItemArray,true);						
					}
					workflowActivityMap[startIndex] = workflowActivityList;
				}
			}
			catch(Exception ex)
			{				
				throw new Exception("Failed to get the WorkflowActivityList", ex);
			}
			return workflowActivityList;
		}

        // <summary>
        /// This method loads all the errored Workflows which is used by Workflow Errors admin page. 
        /// This method will call GetErroredWorkflowItemss stored procedure. 
        /// </summary>
        /// <param name="connectionString">Database connection string</param>
        /// <param name="args">Is expected to contain two arguments - Domain user Id and Module Type</param>        
        public void LoadErrorWorkflows(string connectionString, params object[] args)
        {
            try
            {
                if (args.Length != 2)
                {
                    throw new Exception("Humanworkflow loaderrorworkflows requires domain user Id and moduletype");
                }
                else
                {
                    workflowErrorItemMap.Clear();

                    DataContainer = DataAccess.GetDataSet(InsightConnection,
                            "GetErroredWorkflowItems", Utility.DataAccess.BuildSqlParameterArray(
                                "@DomainUserId", SqlDbType.Int, (int)args[0],
                            "@moduleType", SqlDbType.Char, (string)args[1]));

                    if (DataContainer.Tables.Count == 1)
                        DataContainer.Tables[0].TableName = "original";
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to load Errored Workflows", ex);
            }
        }

        /// <summary>
        /// This method is used load WorkflowErrorItemMap hashtable which gets bind on WorkflowErrorActivityDetail page on the datagrid.
        /// </summary>
        /// <param name="startIndex">Start Index</param>
        /// <param name="count">Number of records</param>
        /// <returns>Datatable used by grid on Workflow Error Activity page</returns>
        public DataTable GetErroredWorkflowItems(int startIndex, int count)
        {
            DataTable workflowErrorList;
            try
            {
                workflowErrorList = workflowErrorItemMap[startIndex] as DataTable;
                if (workflowErrorList == null)
                {
                    workflowErrorList = new DataTable();
                    DataTable dataTable = DataContainer.Tables["original"];
                    workflowErrorList = dataTable.Clone();
                    for (int iCount = startIndex, end = Math.Min(iCount + count, dataTable.Rows.Count); iCount < end; ++iCount)
                    {
                        workflowErrorList.LoadDataRow(dataTable.Rows[iCount].ItemArray, true);
                    }
                    workflowErrorItemMap[startIndex] = workflowErrorList;
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Failed to get the WorkflowErrorItems", ex);
            }
            return workflowErrorList;
        }

		/// <summary>
		/// Workflow Item Id is an internal id stored in SWExecute table, which is a Workflow table. This Id is required in various places
		/// especially when we are doing Skelta API calls or Skelta report etc.
		/// There is a cross referenced table named ProtocolProcess_WorkFlow_Map designed to bridge Application and Workflow. This table has Skelta Execution Id
		/// and Protocol Process Id. This reference gets set after Protocol Process gets submitted to Workflow.
		/// This method gets Execution Id (Workflow Item Id) for given Protocol Process Id using the above mentioned
		/// cross reference table. 		
		/// </summary>
		/// <param name="protocolProcessID">Protocol Process Id</param> 
		/// <returns>Workflow execution Id</returns> 
		public int GetWorkflowItemId(int protocolProcessID)
		{
			int itemId = 0;			
			try
			{																			
				DataSet wfPPItemMap = new DataSet();
                wfPPItemMap = DataAccess.GetDataSet(InsightConnection,
					"GetWorkflowMapData",Utility.DataAccess.BuildSqlParameterArray(
							"@ProtocolProcessId",SqlDbType.Int,protocolProcessID,
							"@ExecutionId",SqlDbType.Int,0 ));

				if (wfPPItemMap.Tables.Count > 0)
				{
					if (wfPPItemMap.Tables[0].Rows.Count > 0)				
						itemId = Int32.Parse(wfPPItemMap.Tables[0].Rows[0]["ExecutionID"].ToString());					
				}
				
			}	
			catch (Exception ex)
			{				
				throw new Exception("Unable to get Workflow Item from mapping table", ex);
			}
			return itemId;

		}


		public int GetWorkflowItemIdByType(int protocolProcessID, string type)
		{
			int itemId = 0;			
			try
			{																			
				DataSet wfPPItemMap = new DataSet();
                wfPPItemMap = DataAccess.GetDataSet(InsightConnection,
					"GetWorkflowMapDataByType",Utility.DataAccess.BuildSqlParameterArray(
					"@ProtocolProcessId",SqlDbType.Int,protocolProcessID,
					"@ExecutionId",SqlDbType.Int,0,	
					"@type", SqlDbType.VarChar, type ));

				if (wfPPItemMap.Tables.Count > 0)
				{
					if (wfPPItemMap.Tables[0].Rows.Count > 0)				
						itemId = Int32.Parse(wfPPItemMap.Tables[0].Rows[0]["ExecutionID"].ToString());					
				}
				
			}	
			catch (Exception ex)
			{				
				throw new Exception("Unable to get Workflow Item from mapping table", ex);
			}
			return itemId;

		}

		/// <summary>
		/// This method will return the list of users associated to the particular Protocol Process and for particular Role.
		/// The return list will be used by Skelta WorkFlow engine to move the WorkFlow items within the WorkFlow in different steps.
		/// This method will get called from the custom action and return an arralist which will update the Array variables in Workflow engine. 
		/// These Array variables will be used by Skelta to send the items to particular user within the WorkFlow.
		/// </summary>
		/// <param name="protocolId">Protocol Id</param> 
		/// <param name="protocolProcessID">Protocol Process Id</param> 
		/// <param name="roleId">Role Id</param>
		public ArrayList GetWorkFlowUsers(int protocolId, int protocolProcessID, int roleId)
		{		
			ArrayList userList = new ArrayList();
			try
			{
               // System.Diagnostics.Debugger.Break();
				int roleIdToWorkOn = 0;
				bool ignoreRest = false; //This flag is used to avaoid going in the for loop below.
				bool workflowRole = true; //This flag is used to do different action in the for loop below
				
				InsightHumans.ProtocolProcess protocolProcess = GetProtocolProcess(protocolProcessID);
				//Workflow behaves defferent for different roles. These are roles people playing in the application
				//(E.g. Principle Investigator, Departmenet Chief, Submitter etc.)
				switch (roleId)
				{
					case InsightHumans.Constants.WorkflowRoleType.DepartmentChair:
						//Get PI, as PI's Department chair Id needs to be in the arraylist
						roleIdToWorkOn = InsightHumans.Constants.StaffRoleType.PrincipalInvestigator;  						
						break;
					case InsightHumans.Constants.WorkflowRoleType.SiteDepartmentChair:
						//Get Site PI, as Site PI's Department chair needs to be in the arraylist
						roleIdToWorkOn = InsightHumans.Constants.StaffRoleType.SiteResponsibleInvestigator;						
						break;
					case InsightHumans.Constants.WorkflowRoleType.SiteIRBChair:
						//Get Site PI, as we need to get the site of Site PI and then get the IRB chair 
						//from the database for that site.
						roleIdToWorkOn = InsightHumans.Constants.StaffRoleType.SiteResponsibleInvestigator;												
						break;
					case InsightHumans.Constants.WorkflowRoleType.HROIntake:
						//Get person Id for HRO Intake from the database table and insert that Id in the
						//arraylist.						
						userList = GetWorkflowPeople(DomainId,HROIntake,protocolProcessID);						
						ignoreRest = true;						
						break;
                    case InsightHumans.Constants.WorkflowRoleType.SRACIntakeUser:
                        //Get person Id for SRAC Intake from the database table and insert that Id in the
                        //arraylist.The animals only deals with only one organization(MGH) and that two at the organization level 						
                        userList = GetWorkflowPeople(2, SRACIntake, protocolProcessID);
                        ignoreRest = true;
                        break;
					case InsightHumans.Constants.WorkflowRoleType.Submitter:
						//Get Submitter ID, Submitter ID is on Protocol Prpocess level.
						userList.Add(protocolProcess.SubmitterId);
						ignoreRest = true;
						break;
					default: //All other Roles like PI, SitePI and Study Staff
						roleIdToWorkOn = roleId;
						workflowRole = false;
						break;
				}
								
				InsightHumans.StaffPerson  staffPerson = null;
				//bool addedHROAdmin = false;
				if (!ignoreRest) //No need to go further arraylist is generated directly.
				{																			
					ArrayList studyStaffList = GetStudyStaff(protocolProcess); 
					int staffCount = studyStaffList.Count; 
					for(int count = 0; count < staffCount; ++count)
					{
						staffPerson = (InsightHumans.StaffPerson) studyStaffList[count];										
						if (staffPerson.RoleId == roleIdToWorkOn)
						{
							//Workflow roles are handled seperately. They are not straight forward.
							//At least one more level of indirection is there.
							if (!workflowRole) 							
							{
								//Here test whether the user has e-mail or not if not then use default users. 								
								DataSet wfEmailCheck = new DataSet();
								wfEmailCheck = DataAccess.GetDataSet(InsightConnection,
									"GetSubstitutePersonIfEmailBlank",
                                    Utility.DataAccess.BuildSqlParameterArray("@userId",SqlDbType.Int,staffPerson.UserId,
                                                                              "@protocolId",SqlDbType.Int,protocolId));
								
								for (int iCount = 0; iCount <= wfEmailCheck.Tables[0].Rows.Count - 1; ++iCount)
								{
									userList.Add(Int32.Parse(wfEmailCheck.Tables[0].Rows[iCount]["UserId"].ToString()));											
								}															
							}
							else //We got the staffPerson we want
								break;
						}
					}
					//Take care of repeated Ids as there is a chance of having duplicate IDs when user
				}

				if ((workflowRole) && (!ignoreRest))
				{
					if ((roleId == InsightHumans.Constants.WorkflowRoleType.DepartmentChair) ||
						(roleId == InsightHumans.Constants.WorkflowRoleType.SiteDepartmentChair) )
					{
                        /*The following loop is included to fix the trackit #5294.
                        Bug Description: No matter How many Site-PIs we have in the study, only one SitePI was assigned the activity.                         
                         */
                        ArrayList studyStaffList = GetStudyStaff(protocolProcess); 
					    int staffCount = studyStaffList.Count;
                        for (int count = 0; count < staffCount; ++count)
                        {
                            staffPerson = (InsightHumans.StaffPerson)studyStaffList[count];
                            if (staffPerson.RoleId == roleIdToWorkOn)
                            {
                                ArrayList organizationPersonList = new ArrayList();
                                organizationPersonList = GetPersonForOrganization(staffPerson.OrganizationId, protocolId);

                                for (int iPersonCount = 0; iPersonCount <= organizationPersonList.Count - 1; ++iPersonCount)
                                {
                                    userList.Add(organizationPersonList[iPersonCount]);
                                }
                            }
                        }
						
					} 
					else if (roleId == InsightHumans.Constants.WorkflowRoleType.SiteIRBChair)
					{												
						userList = GetWorkflowPeople(staffPerson.OrganizationId, IRBChair,protocolProcessID);
					}					
				}
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to get workflow users", ex);
			}
			return userList;
		}

        /// <summary>
        /// This method will return the list of users associated to the particular Protocol Process and for particular Role.
        /// The return list will be used by Skelta WorkFlow engine to move the WorkFlow items within the WorkFlow in different steps.
        /// This method will get called from the custom action and return an arralist which will update the Array variables in Workflow engine. 
        /// These Array variables will be used by Skelta to send the items to particular user within the WorkFlow.
        /// </summary>
        /// <param name="protocolId">Protocol Id</param> 
        /// <param name="protocolProcessID">Protocol Process Id</param> 
        /// <param name="roleId">Role Id</param>
        public ArrayList GetWorkFlowUsers(int protocolId, int protocolProcessID, int roleId, int OrganizationId)
        {
            ArrayList userList = new ArrayList();
            try
            {
                // System.Diagnostics.Debugger.Break();
                int roleIdToWorkOn = 0;
                bool ignoreRest = false; //This flag is used to avaoid going in the for loop below.
                bool workflowRole = true; //This flag is used to do different action in the for loop below

                InsightHumans.ProtocolProcess protocolProcess = GetProtocolProcess(protocolProcessID);
                //Workflow behaves defferent for different roles. These are roles people playing in the application
                //(E.g. Principle Investigator, Departmenet Chief, Submitter etc.)
                switch (roleId)
                {
                    case InsightHumans.Constants.WorkflowRoleType.DepartmentChair:
                        //Get PI, as PI's Department chair Id needs to be in the arraylist
                        roleIdToWorkOn = InsightHumans.Constants.StaffRoleType.PrincipalInvestigator;
                        break;
                    case InsightHumans.Constants.WorkflowRoleType.SiteDepartmentChair:
                        //Get Site PI, as Site PI's Department chair needs to be in the arraylist
                        roleIdToWorkOn = InsightHumans.Constants.StaffRoleType.SiteResponsibleInvestigator;
                        break;
                    case InsightHumans.Constants.WorkflowRoleType.SiteIRBChair:
                        //Get Site PI, as we need to get the site of Site PI and then get the IRB chair 
                        //from the database for that site.
                        roleIdToWorkOn = InsightHumans.Constants.StaffRoleType.SiteResponsibleInvestigator;
                        break;
                    case InsightHumans.Constants.WorkflowRoleType.HROIntake:
                        //Get person Id for HRO Intake from the database table and insert that Id in the
                        //arraylist.						
                        userList = GetWorkflowPeople(OrganizationId, HROIntake, protocolProcessID);
                        ignoreRest = true;
                        break;
                    case InsightHumans.Constants.WorkflowRoleType.SRACIntakeUser:
                        //Get person Id for SRAC Intake from the database table and insert that Id in the
                        //arraylist.The animals only deals with only one organization(MGH) and that two at the organization level 						
                        userList = GetWorkflowPeople(2, SRACIntake, protocolProcessID);
                        ignoreRest = true;
                        break;
                    case InsightHumans.Constants.WorkflowRoleType.Submitter:
                        //Get Submitter ID, Submitter ID is on Protocol Prpocess level.
                        userList.Add(protocolProcess.SubmitterId);
                        ignoreRest = true;
                        break;
                    default: //All other Roles like PI, SitePI and Study Staff
                        roleIdToWorkOn = roleId;
                        workflowRole = false;
                        break;
                }

                InsightHumans.StaffPerson staffPerson = null;
                //bool addedHROAdmin = false;
                if (!ignoreRest) //No need to go further arraylist is generated directly.
                {
                    ArrayList studyStaffList = GetStudyStaff(protocolProcess);
                    int staffCount = studyStaffList.Count;
                    for (int count = 0; count < staffCount; ++count)
                    {
                        staffPerson = (InsightHumans.StaffPerson)studyStaffList[count];
                        if (staffPerson.RoleId == roleIdToWorkOn)
                        {
                            //Workflow roles are handled seperately. They are not straight forward.
                            //At least one more level of indirection is there.
                            if (!workflowRole)
                            {
                                //Here test whether the user has e-mail or not if not then use default users. 								
                                DataSet wfEmailCheck = new DataSet();
                                wfEmailCheck = DataAccess.GetDataSet(InsightConnection,
                                    "GetSubstitutePersonIfEmailBlank",
                                    Utility.DataAccess.BuildSqlParameterArray("@userId", SqlDbType.Int, staffPerson.UserId,
                                                                              "@protocolId", SqlDbType.Int, protocolId));

                                for (int iCount = 0; iCount <= wfEmailCheck.Tables[0].Rows.Count - 1; ++iCount)
                                {
                                    userList.Add(Int32.Parse(wfEmailCheck.Tables[0].Rows[iCount]["UserId"].ToString()));
                                }
                            }
                            else //We got the staffPerson we want
                                break;
                        }
                    }
                    //Take care of repeated Ids as there is a chance of having duplicate IDs when user
                }

                if ((workflowRole) && (!ignoreRest))
                {
                    if ((roleId == InsightHumans.Constants.WorkflowRoleType.DepartmentChair) ||
                        (roleId == InsightHumans.Constants.WorkflowRoleType.SiteDepartmentChair))
                    {
                        /*The following loop is included to fix the trackit #5294.
                        Bug Description: No matter How many Site-PIs we have in the study, only one SitePI was assigned the activity.                         
                         */
                        ArrayList studyStaffList = GetStudyStaff(protocolProcess);
                        int staffCount = studyStaffList.Count;
                        for (int count = 0; count < staffCount; ++count)
                        {
                            staffPerson = (InsightHumans.StaffPerson)studyStaffList[count];
                            if (staffPerson.RoleId == roleIdToWorkOn)
                            {
                                ArrayList organizationPersonList = new ArrayList();
                                organizationPersonList = GetPersonForOrganization(staffPerson.OrganizationId, protocolId);

                                for (int iPersonCount = 0; iPersonCount <= organizationPersonList.Count - 1; ++iPersonCount)
                                {
                                    userList.Add(organizationPersonList[iPersonCount]);
                                }
                            }
                        }

                    }
                    else if (roleId == InsightHumans.Constants.WorkflowRoleType.SiteIRBChair)
                    {
                        userList = GetWorkflowPeople(staffPerson.OrganizationId, IRBChair, protocolProcessID);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to get workflow users", ex);
            }
            return userList;
        }
		
		/// <summary>
		/// This method gets User Ids for given role and organization.
		/// There is a table named Organization_WorkflowRole_Person_Map which has information regarding these users.
		/// This table has a person Id for different roles (like IRBChair or BWHInvestigationalDrugServiceContact) for
		/// different organization.
		/// </summary>
		/// <param name="organizationId">Organization Id</param>
		/// <param name="workflowRole">Workflow related role</param>
		/// <returns>ArrayList of Person Id</returns>		
		public ArrayList GetWorkflowPeople(int organizationId, string workflowRole, int protocolProcessId)
		{
			ArrayList userList = new ArrayList();
			try
			{														
				DataSet wfPersonDataset = new DataSet();
                if (workflowRole == HROIntake)
                {
                    string workflowType = GetContextVariables("Content", "workflowtype", protocolProcessId);
                    if ((workflowType != "NINT_IR") && (workflowType != "INT_IR") && (workflowType != "CR"))
                    {
                        workflowType = "Default";
                    }
                    wfPersonDataset = DataAccess.GetDataSet(InsightConnection,
                        "GetWorkflowPerson", Utility.DataAccess.BuildSqlParameterArray("@orgId", SqlDbType.Int, organizationId, "@workflowRole", SqlDbType.VarChar, workflowRole, "@workflowType", SqlDbType.VarChar, workflowType));

                }
                else if (workflowRole == SRACIntake)
                {
                    wfPersonDataset = DataAccess.GetDataSet(InsightConnection,
                         "GetWorkflowPerson", Utility.DataAccess.BuildSqlParameterArray("@orgId", SqlDbType.Int, organizationId, "@workflowRole", SqlDbType.VarChar, workflowRole, "@workflowType", SqlDbType.VarChar, "Default"));
                }
                else
                {
                    wfPersonDataset = DataAccess.GetDataSet(InsightConnection,
                        "GetWorkflowPerson", Utility.DataAccess.BuildSqlParameterArray("@orgId", SqlDbType.Int, organizationId, "@workflowRole", SqlDbType.VarChar, workflowRole));
                }

				for (int iCount = 0; iCount <= wfPersonDataset.Tables[0].Rows.Count - 1; ++iCount)					
				{
					userList.Add(Int32.Parse(wfPersonDataset.Tables[0].Rows[iCount]["PersonId"].ToString())); 
				}								
			}	
			catch (Exception ex)
			{				
				throw new Exception("Unable to get Workflow people", ex);
			}
			return userList;
		}	

		/// <summary>
		/// This method gets User Id for given role and organization.
		/// There is a table named Organization_WorkflowRole_Person_Map which has information regarding these users.
		/// This table has a person Id for different roles (like IRBChair or BWHInvestigationalDrugServiceContact) for
		/// different organization.
		/// </summary>
		/// <param name="organizationId">Organization Id</param>
		/// <param name="workflowRole">Workflow related role</param>
		/// <returns>Person Id</returns>		
		public int GetWorkflowPerson(int organizationId, string workflowRole)
		{
			int personId = 0;
			try
			{														
				DataSet wfPersonDataset = new DataSet();
				wfPersonDataset = DataAccess.GetDataSet(InsightConnection,
					"GetWorkflowPerson",Utility.DataAccess.BuildSqlParameterArray("@orgId",SqlDbType.Int,organizationId,"@workflowRole",SqlDbType.VarChar,workflowRole));
	
				personId = Int32.Parse(wfPersonDataset.Tables[0].Rows[0]["PersonId"].ToString()); 
				
			}	
			catch (Exception ex)
			{				
				throw new Exception("Unable to get Workflow person", ex);
			}
			return personId;
		}

        /// <summary>
        /// This method will start the WorkFlow process. The submitter submits the Protocol Process (WorkFlow Item) to the WorkFlow. 
        /// The submitted WorkFlow goes to PI's queue. This method has two important activities. 
        /// 1.Start the WorkFlow using Skelta's Execute method. First parameter of this method
        /// is user name, PI's person ID will be there. This parameter is for application to send application specific data to the
        /// WorkFlow. The data gets sent in XML format. The format is:
        ///  <application> <field1>Field1 data</field1><field2>Field2 data</field2>......</application>
        ///  2. Create an entry in ProtocolProcess_WorkFlow_Map table.
        /// </summary>	
        /// <param name="protocolProcess">Protocol Process Object</param> 	
        public void InitiateWorkFlow(InsightHumans.ProtocolProcess protocolProcess, string WFType, string mainWorkFlow)
        {
            try
            {
                //System.Diagnostics.Debugger.Break();
                ///TODO: Where to pass in the t ype to k now which WF it will be????
                InsightHumans.Protocol protocol = new InsightHumans.Protocol(base.CachePolicy);
                protocol.Load(InsightConnection, protocolProcess.ProtocolId);

                StringBuilder executeStringBuilder = new StringBuilder("<application><protocolid>");
                executeStringBuilder.Append(protocolProcess.ProtocolId.ToString());
                executeStringBuilder.Append("</protocolid><ppid>");
                executeStringBuilder.Append(protocolProcess.Id.ToString());
                executeStringBuilder.Append("</ppid><protocolname>");
                executeStringBuilder.Append(protocolProcess.Name);
                executeStringBuilder.Append("</protocolname><protocoltitle>");
                //Encoded the protocol title twice since, the protocoltitle is getting decoded back to original value each time the context is accessed.
                executeStringBuilder.Append(System.Web.HttpUtility.HtmlEncode(System.Web.HttpUtility.HtmlEncode(protocol.Title)));
                executeStringBuilder.Append("</protocoltitle><pptype>");
                executeStringBuilder.Append(protocolProcess.Type);
                ////executeStringBuilder.Append("</pptype></application>");
                executeStringBuilder.Append("</pptype><insightApplicationName>");
                //Added InsightApplication name ato configure multiple sites for single installation of skelta
                executeStringBuilder.Append(Utility.Settings.GetKeyValue("InsightApplicationName", ""));
                executeStringBuilder.Append("</insightApplicationName></application>");


                //Set it to member level variable
                protocolProcessMember = protocolProcess;

                //Get PI for the Protocol Process
                ArrayList piList = GetWorkFlowUsers(protocolProcess.ProtocolId, protocolProcess.Id, InsightHumans.Constants.StaffRoleType.PrincipalInvestigator);

                if (piList.Count > 0)
                {
                    //string piUserID = piList[0].ToString();				
                    SkeltaEngine.Client protocolAppWF = new SkeltaEngine.Client(InsightApplicationName, mainWorkFlow);
                    int executionID = protocolAppWF.Execute(piList[0].ToString(), executeStringBuilder.ToString());
                    protocolAppWF.Close();
                    //The execution id which we re getting is the id for the main (umbrella) workflow. We really need the workflow id for child whcih is the next in the line.
                    //CreateProtocolProcessWorkFlowMap(pProcess.Id,executionID+1);				
                }
                else
                { throw new Exception("There is no Principal Investigator associated with the application."); }

            }
            catch (Exception ex)
            {
                throw new Exception("Unable to execute the Workflow", ex);
            }
        }																
				
		/// <summary>
		/// This method checks whether there is Site IRB chair validation required for the particular
		/// Prootocol Process. If the site is NWH, NSMC or SRH then Site IRB chair validation is required
		/// otherwise it is not required.
		/// </summary>
		/// <param name="protocolProcessID">Protocol Process Id</param> 
		/// <returns>0 - Not Present; 1- Present</returns>
		public int IsSiteIRBChair(int protocolProcessID)
		{
			string orgName = GetSite(protocolProcessID);			
			return ((orgName == NWHOrganization) || (orgName == NSMCOrganization) || (orgName == SRHOrganization)) ? 1 : 0;
		}
		
		/// <summary>
		/// This method checks whether there is a Site PI associated with the Protocol Process.
		/// This goes through study staff collection and sees whether there is Site Responsible Investigator role
		/// present in the collection.
		/// If it is present then return 1 else return 0.
		/// </summary>
		/// <param name="protocolProcessID">Protocol Process Id</param> 
		/// <returns>0 - Not Present; 1- Present</returns>
		public int IsSitePIPresent(int protocolProcessID)
		{			
			int sitePIPresent = 0;
			try
			{							
				InsightHumans.ProtocolProcess protocolProcess = GetProtocolProcess(protocolProcessID);
				ArrayList studyStaffList = GetStudyStaff(protocolProcess);
				InsightHumans.StaffPerson  staffPerson;
				int staffCount = staffList.Count; 
			
				for(int count = 0; count < staffCount; ++count)
				{
					staffPerson = (InsightHumans.StaffPerson) studyStaffList[count];
					if (staffPerson.RoleId == InsightHumans.Constants.StaffRoleType.SiteResponsibleInvestigator)
					{
						sitePIPresent = 1; 
						break;
					}
				}	
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to check Site PI association", ex);
			}
			return sitePIPresent;
				
		}
		
		/// <summary>
		/// This method gets called from custom action of Skelta WorkFlow. ProtocolProcess object
		/// gets loaded using the passed Protocol Process ID and Lock method on that objects gets called.
		/// </summary>
		/// <param name="protocolProcessID">Protocol Process Id</param> 
		public void ProtocolProcessLock(int protocolProcessID)
		{			
			try
			{		
				InsightHumans.ProtocolProcess protocolProcess = GetProtocolProcess(protocolProcessID);				 
				protocolProcess.Lock(InsightConnection,base.CachePolicy,null);				
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to lock Protocol Process",ex);
			}
		}

		/// <summary>
		/// This method gets called from custom action of WorkFlow. ProtocolProcess object
		/// gets loaded using the passed Protocol Process ID and Unlock method on that objects gets called.
		/// </summary>
		/// <param name="protocolProcessID">Protocol Process Id</param> 
		public void ProtocolProcessUnLock(int protocolProcessID)
		{			
			try
			{	
				InsightHumans.ProtocolProcess protocolProcess = GetProtocolProcess(protocolProcessID);				 
				protocolProcess.Unlock(InsightConnection,base.CachePolicy,null);												
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to unlock Protocol Process",ex);
			}
		}		

		/// <summary>
		/// This method saves the skelta context variables at runtime
		/// </summary>
		/// <param name="varName">Variable Name</param>
		/// <param name="varvalues">Value for the context variable</param>
		/// <param name="ppId">Protocol process id for which the workflow context needs to be retrieved</param>
		/// <returns></returns>
		public void SetContextVariables( string varName,object varValue,int protocolProcessId)
		{
			try
			{
				SkeltaEngine.Context workflowContext =null;
				workflowContext= GetWorkFlowContext(protocolProcessId);

				if(workflowContext!=null)
				{
					workflowContext.Variables[varName].Value=varValue;
					workflowContext.SaveVariables();
					workflowContext.Close();
				}
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to set the context variables",ex);
			}
		}

		public void SetContextVariables( string varName,object varValue,int protocolProcessId, string type)
		{
			try
			{
				SkeltaEngine.Context workflowContext =null;
				workflowContext= GetWorkFlowContext(protocolProcessId, type);

				if(workflowContext!=null)
				{
					workflowContext.Variables[varName].Value=varValue;
					workflowContext.SaveVariables();
					workflowContext.Close();
				}
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to set the context variables",ex);
			}
		}

		/// <summary>
		/// This method gets called from custom action of WorkFlow. 
		/// The Status property of Protocol Process gets updated in this method.		
		/// </summary>
		/// <param name="status">Status to set(Pending or Submitted)</param> 
		/// <param name="protocolProcessID">Protocol Process Id</param> 
		/// <param name="appType">Protocol Application type (i.e. different process - Initial Review, Amendment, Continuing Review etc.)</param> 
		public void SetProtocolProcessStatus(string status, int protocolProcessID, string appType)
		{			
			try
			{				
				InsightHumans.ProtocolProcess protocolProcess = GetProtocolProcess(protocolProcessID);
				protocolProcess.Status = status;
				protocolProcess.Save(InsightConnection); 
				InsightHumans.Protocol protocol = new InsightHumans.Protocol(base.CachePolicy);
				protocol.Load(InsightConnection, protocolProcess.ProtocolId);
								
				bool protocolStatusChange = false;
                if (appType == InsightHumans.Constants.ProtocolProcessType.InitialReview || appType == InsightHumans.Constants.AnimalProtocolProcessType.InitialReview)
				{
					switch (status)
					{
						case InsightHumans.Constants.ProtocolProcessStatus.Pending: 
							protocol.OverallStatusId =  (int)InsightHumans.Constants.ProtocolOverallStatus.Pending; 
							protocolStatusChange = true;							
							break;
						case InsightHumans.Constants.ProtocolProcessStatus.Submitted:
							protocol.OverallStatusId =  (int)InsightHumans.Constants.ProtocolOverallStatus.Submitted; 
							protocolStatusChange = true;
							break;
						default:							
							break;
					}
					if (protocolStatusChange)
						protocol.Save(InsightConnection);
					
				}				
				
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to change status of Protocol Process",ex);
			}
		}	

        /// <summary>
		/// This method gets called from custom action of WorkFlow. 
		/// The Status property of Protocol Process gets updated in this method.		
		/// </summary>
		/// <param name="status">Status to set(Pending or Submitted)</param> 
		/// <param name="protocolProcessID">Protocol Process Id</param> 
		/// <param name="appType">Protocol Application type (i.e. different process - Initial Review, Amendment, Continuing Review etc.)</param> 
		public void SetMovedToRexFlag(int protocolProcessID)
		{			
			try
			{				
				// Now set the flag for the process that it has been submitted to Rex.
                Utility.DataAccess.ExecuteNonQuery(InsightConnection,
                "UpdateMoveToRexSatusForProcess",
                Utility.DataAccess.BuildSqlParameterArray(
                "@processId", SqlDbType.Int, protocolProcessID));
				
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to change status of Protocol Process",ex);
			}
		}	
        

		/// <summary>
		/// Sort the list by the specified column.
		/// If the column to be sorted is the same as what was last sorted on, the sort sequence is toggled. 
		/// Else, the sort sequence is set to ascending.
		/// </summary>
		/// <param name="columnName">Column to sort by</param>
		public void Sort(string columnName)
		{
			workflowActivityMap.Clear();
			sortAscending = (sortColumn == columnName) ? !sortAscending : AscendingSortSequence;
			sortColumn = columnName;

			DataTable dataTable = DataContainer.Tables["original"];
			DataView dataView = dataTable.DefaultView;
			dataView.Sort = string.Format("{0} {1}", columnName, sortAscending ? Utils.Constants.SortViewAscending : Utils.Constants.SortViewDescending);

			DataTable sortedDataTable = dataTable.Clone();
			foreach (DataRowView rowView in dataView)
			{
				sortedDataTable.ImportRow(rowView.Row);
			}
			DataContainer.Tables.Remove("original");
			DataContainer.Tables.Add(sortedDataTable);
		}																									
				
		#endregion

		# region private methods
		/// <summary>
		/// //Gets the Performace sites selected in the initial review.(This is used only when the current process doesn't have the performance sites questionnaire)
		/// </summary>
		/// <param name="ProtocolId">The protocol whose initial review process has to be manipulated</param>
		/// <param name="isBWH">boolean variable(Holds the status of the bwh performance site(checked\unchecked))</param>
		/// <param name="isMGH">boolean variable(Holds the status of the mgh performance site(checked\unchecked))</param>
		
		private void GetPerformanceSites(int protocolId,out bool isBWH,out bool isMGH)
		{
			isBWH=false;
			isMGH=false;
			ArrayList existingProcesses ; 
			existingProcesses = Humans.Protocol.GetProtocolProcesses(protocolId,base.CachePolicy);
			foreach (Humans.ProtocolProcess protocolProcess in existingProcesses)
			{
				if (protocolProcess.Type==Humans.Constants.ProtocolProcessType.InitialReview)
				{
					Humans.ProtocolVersion pVersion; 
					ArrayList qAnswers ; 
					pVersion =protocolProcess.GetLatestProtocolVersion(false,base.CachePolicy);
					qAnswers = pVersion.QuestionnaireAnswers;
					foreach (FormsManagement.QuestionnaireAnswer questionnaireAnswer   in qAnswers)
					{
						if ((questionnaireAnswer.QuestionnaireVersion.Questionnaire.Name == "PerformanceSites" )||(questionnaireAnswer.QuestionnaireVersion.Questionnaire.Name == "Performance Sites" ))
						{
							FormsManagement.QuestionnaireVersion qV = questionnaireAnswer.QuestionnaireVersion;
							if (qV != null)
							{
								ArrayList items=qV.Items;
                                foreach (FormsManagement.QuestionnaireItem qI in items)
								{
									if ((qI.Name.ToLower().Trim()=="sitemgh")||(qI.Name.ToLower().Trim()=="sitebwh"))
									{
										string siteBWH = (questionnaireAnswer.GetAnswers("SiteBWH").Count == 0)? string.Empty : ((FormsManagement.Answer)questionnaireAnswer.GetAnswers("SiteBWH")[0]).Value;
										string siteMGH = (questionnaireAnswer.GetAnswers("SiteMGH").Count == 0)? string.Empty : ((FormsManagement.Answer)questionnaireAnswer.GetAnswers("SiteMGH")[0]).Value;

										if (siteBWH == "BWH") //Whether BWH is checked in the forms
										{
											isBWH = true;
										}
										if (siteMGH == "MGH") //Whether MGH is checked in the forms
										{
											isMGH = true;
										}
									}
									
								}
								return;
							}
						}
					}
				}
			}			
			
		}
		
		/// <summary>
		/// This method gets signoff person id for given organization. For every organization there is an assigned signoff person.
		/// This information is maintained in Organization_Signoff_Map table. This method gets signed off person for
		/// given organization.
		/// </summary>
		/// <param name="organizationId">Organization Id</param>
		/// <returns>Person Id</returns>
		private ArrayList GetPersonForOrganization(int organizationId,int protocolId)
		{
			ArrayList personIds = new ArrayList(); 
			int personId = 0;
			try
			{																			
				DataSet wfPersonDataset = new DataSet();
				wfPersonDataset = DataAccess.GetDataSet(InsightConnection,
					"GetChiefList",Utility.DataAccess.BuildSqlParameterArray("@OrgId",SqlDbType.Int,organizationId));
				//Check whether the delegate is set for the person. If the delegate is set for the person then use that person
				//Otherwise set the same person.
				if ((bool)(wfPersonDataset.Tables[0].Rows[0]["HasDelegate"]))
					personId = (int)(wfPersonDataset.Tables[0].Rows[0]["DelegatePersonId"]); 
				else
					personId = (int)(wfPersonDataset.Tables[0].Rows[0]["SignOffPersonId"]);

				//If the person doesn' have e-mail Id then we need to substitute HRO admin Ids with it. 
				DataSet wfEmailCheck = new DataSet();
				wfEmailCheck = DataAccess.GetDataSet(InsightConnection,
					"GetSubstitutePersonIfEmailBlank",
                    Utility.DataAccess.BuildSqlParameterArray("@userId",SqlDbType.Int,personId,
                                                            "@protocolId",SqlDbType.Int,protocolId));
				for (int iCount = 0; iCount <= wfEmailCheck.Tables[0].Rows.Count - 1; ++iCount)
				{
					personIds.Add(Int32.Parse(wfEmailCheck.Tables[0].Rows[iCount]["UserId"].ToString()));
				}
				
				return personIds;
			}	
			catch (Exception ex)
			{				
				throw new Exception("Unable to ChiefList from mapping table", ex);
			}			
		}

		/// <summary>
		/// This method gets the workflow context variables.
		/// </summary>
		/// <param name="varType">Type - Content or Variable</param>
		/// <param name="varName">Variable Name</param>
		/// <param name="ppId">Protocol Process ID</param>
		/// <returns></returns>
		private string GetContextVariables(string varType, string varName, int protocolProcessId)
		{
			string variableValue = string.Empty;
			//Creating instance of Context object;
			SkeltaEngine.Context workflowContext = null;
			try
			{
				workflowContext= GetWorkFlowContext(protocolProcessId);
				if(workflowContext != null)
				{
					variableValue=(varType == "Content")? workflowContext.Contents[varName].Value.ToString(): workflowContext.Variables[varName].Value.ToString();
					//Retrieve Content value using Context object						
					workflowContext.Close();
				}
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to get context variables",ex);
			}
			return variableValue;
		}

        private string GetContextVariables(string varType, string varName, int protocolProcessId, string type)
        {
            string variableValue = string.Empty;
            //Creating instance of Context object;
            SkeltaEngine.Context workflowContext = null;
            try
            {
                workflowContext = GetWorkFlowContext(protocolProcessId, type);
                if (workflowContext != null)
                {
                    variableValue = (varType == "Content") ? workflowContext.Contents[varName].Value.ToString() : workflowContext.Variables[varName].Value.ToString();
                    //Retrieve Content value using Context object						
                    workflowContext.Close();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to get context variables", ex);
            }
            return variableValue;
        }

		/// <summary>
		/// This Method returns the Questionnaire Answers for a protocol version
		/// </summary>
		/// <param name="protocolProcess">The process to which the questionniare is assosiated with</param>
		/// <returns>ArrayList of QuestionnaireAnswers for a protocolVersion</returns>
		private ArrayList GetQuestionnaireAnswers(InsightHumans.ProtocolProcess protocolProcess)
		{
			try
			{
				Humans.ProtocolVersion protocolVersion = protocolProcess.GetLatestProtocolVersion(false,base.CachePolicy);
				return protocolVersion.QuestionnaireAnswers;
			}
			catch(Exception ex)
			{throw new Exception("Failed to get the Questionnaire Answers. Error occurred at HumansWorkFlow.GetQuestionnaireAnswers() " + ex.InnerException.ToString());}
		}

		/// <summary>
		/// This method returns the site for passed protocol process ID.
		/// This site will be used to move WorkFlow in particular direction.
		/// Example: If Site is NWH, NSMC or SRH then the WorkFlow object goes from 
		/// PI (on accept) to Site IRB; otherwise it goes to HRO Intake person.
		/// </summary>
		/// <param name="ppID">Protocol Process ID</param> 
		private string GetSite(int protocolProcessID)
		{			
			string site = string.Empty;	
			try
			{																	
				PHSRAG.Insight21.Humans.ProtocolProcess protocolProcess = GetProtocolProcess(protocolProcessID);
				ArrayList studyStaffList = GetStudyStaff(protocolProcess);
				InsightHumans.StaffPerson  staffPerson;
				int staffCount = staffList.Count; 
			
				for(int count = 0; count < staffCount; ++count)
				{
					staffPerson = (InsightHumans.StaffPerson) studyStaffList[count];
					if (staffPerson.RoleId == InsightHumans.Constants.StaffRoleType.SiteResponsibleInvestigator)
					{						
						site = staffPerson.InstitutionalName;
						break;
					}
				}					
			}
			catch (Exception ex)
			{				
				throw new Exception("Unable to get Site for Protocol process", ex);
			}
			return site;
		}

		/// <summary>
		/// This method uses Skelta APIs to get Workflow engine context (Skelta content or Skelta variable) variables. 		
		/// </summary>
		/// <param name="varType">Type - Content or Variable</param>
		/// <param name="varName">Variable Name</param>
		/// <param name="ppId">Protocol Process ID</param>
		/// <returns></returns>
		public SkeltaEngine.Context GetWorkFlowContext(int protocolProcessId)
		{
			//Creating instance of Context object;
			SkeltaEngine.Context workflowContext = null;
			try
			{
				//Creating instance of Config class object to get Connection string and datasource type.
				SkeltaWorkFlow.Config workflowConfig;				
				//Creating instance of RunTime object
				SkeltaEngine.RunTime workflowRuntime;
				//Creating instance of Datahandler object
				SkeltaWorkFlow.Interfaces.IDataHandler workflowHandler;
				
				//Initializing Config class object. 
				//Config class object retrieves all the information of the application that is configured 
				//in Workflow.NET.Config.Xml file.
				workflowConfig = new SkeltaWorkFlow.Config(InsightApplicationName);
				//Initializing DataHandler object which is used for database operations also to get the 
				//Workflow Context details.
				workflowHandler = SkeltaWorkFlow.Storage.DataHandlerFactory.GetDataHandler(InsightConnection, workflowConfig.DataSourceType);
				//Initializing Runtime object to get the status of the workflow and actions
				workflowRuntime = SkeltaEngine.RunTime.GetRuntime(System.Net.Dns.GetHostName(), InsightApplicationName,false);
				//Initializing the Workflow Context object to get the Workflow details like Application Name, 
				//Workflow Name, Content and Variables value
				//Here ExecutionId, Runtime object and Datahandler object should be passed.
				int executionId = GetWorkflowItemId(protocolProcessId);  
        
				workflowContext= SkeltaEngine.Context.GetContext(executionId,workflowRuntime,workflowHandler);
			}
			catch(Exception ex)
			{
				throw new Exception("Unable to get workflow context",ex);
			}
			return workflowContext;
		}


		private SkeltaEngine.Context GetWorkFlowContext(int protocolProcessId, string type )
		{
			//Creating instance of Context object;
			SkeltaEngine.Context workflowContext = null;
			try
			{
				//Creating instance of Config class object to get Connection string and datasource type.
				SkeltaWorkFlow.Config workflowConfig;				
				//Creating instance of RunTime object
				SkeltaEngine.RunTime workflowRuntime;
				//Creating instance of Datahandler object
				SkeltaWorkFlow.Interfaces.IDataHandler workflowHandler;
				
				//Initializing Config class object. 
				//Config class object retrieves all the information of the application that is configured 
				//in Workflow.NET.Config.Xml file.
				workflowConfig = new SkeltaWorkFlow.Config(InsightApplicationName);
				//Initializing DataHandler object which is used for database operations also to get the 
				//Workflow Context details.
				workflowHandler = SkeltaWorkFlow.Storage.DataHandlerFactory.GetDataHandler(InsightConnection, workflowConfig.DataSourceType);
				//Initializing Runtime object to get the status of the workflow and actions
				workflowRuntime = SkeltaEngine.RunTime.GetRuntime(System.Net.Dns.GetHostName(), InsightApplicationName,false);
				//Initializing the Workflow Context object to get the Workflow details like Application Name, 
				//Workflow Name, Content and Variables value
				//Here ExecutionId, Runtime object and Datahandler object should be passed.
				int executionId = GetWorkflowItemIdByType(protocolProcessId, type);  
        
				workflowContext= SkeltaEngine.Context.GetContext(executionId,workflowRuntime,workflowHandler);
			}
			catch(Exception ex)
			{
				throw new Exception("Unable to get workflow context",ex);
			}
			return workflowContext;
		}
		#endregion

		#region IDisposable Members

		public void Dispose()
		{		
			workflowActivityMap.Clear();
     		workflowActivityMap = null;
			GC.SuppressFinalize(this);
		}

		#endregion
	}
		#endregion
}
